﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml;
using System.Reflection;
using Vortex.IO;

namespace Vortex.TutorialBrowser {
    
    class ContentEngine {
        public static readonly string SCHEME_RUN_ITEM = "run";

        static readonly string PAGE_TEMPLATE_NAME = "Vortex.Browser.page.html";
		static readonly string SECTION_TEMPLATE_NAME = "Vortex.Browser.section.html";
		static readonly string SCRIPT_FILE_NAME = "Vortex.Browser.jquery15.js";
		static readonly string CONTENT_XML_NAME = "Vortex.Browser.content.xml";

        DirectoryInfo m_BaseDirectory;
        DirectoryInfo m_ImageBaseDirectory;
        DirectoryInfo m_CSSBaseDirectory;
        DirectoryInfo m_CodeBaseDirectory;

        string m_CodeBase;
        string m_DocBase;

        Dictionary<string, ContentItemInfo> m_ItemMap;
        List<ContentItemInfo> m_Items;

        public ContentEngine(string contentDirectory) {
            m_BaseDirectory = new DirectoryInfo(contentDirectory);
            m_ImageBaseDirectory = new DirectoryInfo(contentDirectory + "\\Thumbnails");
            m_CSSBaseDirectory = new DirectoryInfo(contentDirectory + "\\CSS");
            m_CodeBaseDirectory = new DirectoryInfo("..\\..\\Tutorials");

            LoadContentItems();
        }

        private void LoadContentItems () {
            m_ItemMap = new Dictionary<string, ContentItemInfo>();
            m_Items = new List<ContentItemInfo>();

            XmlDocument document = new XmlDocument();
			document.LoadXml(LoadTemplate(CONTENT_XML_NAME));

            XmlNodeList xmlNodeList = document.GetElementsByTagName("content");
            if (xmlNodeList.Count == 1) {
                m_CodeBase = xmlNodeList[0].Attributes["codefile-base"].Value;
                m_DocBase = xmlNodeList[0].Attributes["doc-base"].Value;

                //next is iteration through all tutorial items
                xmlNodeList = xmlNodeList[0].ChildNodes;

                foreach (XmlNode node in xmlNodeList) {
                    ContentItemInfo itemInfo = LoadContentItems(node);
                    m_ItemMap.Add(itemInfo.Id.ToLower(), itemInfo);
                    m_Items.Add(itemInfo);
                }
            } else {
                ThrowContentXMLParsingException();
            }
        }

        private ContentItemInfo LoadContentItems (XmlNode node) {
            ContentItemInfo item = new ContentItemInfo();
            item.Id = node.Attributes["id"].Value;
			item.Filter = node.Attributes["filter"].Value;

            foreach (XmlNode valueNode in node.ChildNodes) {
                string value = valueNode.InnerText;
                switch(valueNode.Name) {
                    case "title":
                        item.Title = value;
                        break;
                    case "description":
                        item.Description = value;
                        break;
                    case "image":
                        item.Image = value;
                        break;
                    case "exec-path":
                        item.ExecPath = value;
                        break;
                    case "doc-id":
                        item.DocURL = DecorateDocPage(value);
                        break;
                    case "codefile-id":
                        item.CodeURL = DecorateCodePage(value);
                        break;
                    case "doc-page":
                        item.DocURL = value;
                        break;
                    case "codefile-page":
                        item.CodeURL = value;
                        break;

                }
            }

            return item;
        }

        private string DecorateDocPage (string value) {
            return m_DocBase.Replace("${id}", value).Replace("http://", "");
        }

        private string DecorateCodePage (string value) {
            return m_CodeBase.Replace("${id}", value).Replace("http://", "");
        }

        private void ThrowContentXMLParsingException () {
            throw new Exception("Invalid format of tutorial browser content description file");
        }

        public string BuildPage() {
            string pageTemplate = LoadTemplate(PAGE_TEMPLATE_NAME);
            string sectionTemplate = LoadTemplate(SECTION_TEMPLATE_NAME);
			string scripts = LoadTemplate(SCRIPT_FILE_NAME);

            StringBuilder builder = new StringBuilder();

            foreach (ContentItemInfo item in m_Items) {
                string sectionContent =
                    sectionTemplate.Replace("${id}", item.Id).Replace("${imageURL}", DecorateImageURL(item.Image))
                    .Replace("${title}", item.Title).Replace("${description}", item.Description)
                    .Replace("${docURL}", item.DocURL ?? "").Replace("${codeURL}", item.CodeURL ?? "").Replace("${filter}", item.Filter);

                builder.Append(sectionContent);
            }

            return pageTemplate.Replace("${scripts}", scripts).Replace("${sections}", builder.ToString()).Replace("${imageDir}", ImageDirectory);
        }

        private string DecorateImageURL (string imageName) {
            return "file:///" + ImageDirectory + "\\" + imageName;
        }

        private string LoadTemplate (string templateFileName) {
			return new ResourceFileInfo(templateFileName).GetContentAsText();
        }

        #region Property Part

        public string BasePath {
            get { return m_BaseDirectory.FullName; }
        }

        public string ImageDirectory {
            get { return m_ImageBaseDirectory.FullName; }
        }

        public string CSSBasePath {
            get { return m_CSSBaseDirectory.FullName; }
        }

        public string CodeBasePath {
            get { return m_CodeBaseDirectory.FullName; }
        }

        public ContentItemInfo GetItemById(string id) {
            return m_ItemMap[id];
        }

        #endregion

        internal ContentItemInfo GetContentItem (string itemId) {
            return m_ItemMap[itemId.ToLower()];
        }
    }

}
